import { unified } from "unified";
import parse from "remark-parse";
import remarkFrontmatter from "remark-frontmatter";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import remarkRehype from "remark-rehype";
import rehypeRaw from "rehype-raw";
import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
import rehypeKatex from "rehype-katex";
import rehypeHighlight from "rehype-highlight";
import rehypeStringify from "rehype-stringify";
import type { Schema } from "hast-util-sanitize";
import rehypekSlug from "rehype-slug";
// 读取目录
import { toc } from "mdast-util-toc";

const katexSchema: Schema = {
  ...defaultSchema,
  attributes: {
    ...defaultSchema.attributes,
    "*": [
      ["className"],
      ["style"],
      ["id"],
      ["href"],
      ["aria-label"],
      ["aria-describedby"],
      ["aria-hidden"],
      ["data-*"],
    ],
    a: [
      ["href"],
      ["id"],
      ["className"],
      ["aria-label"],
      ["aria-describedby"],
      ["data-footnote-ref"],
      ["data-footnote-backref"],
    ],
    sup: [["id"], ["data-footnote-ref"], ["aria-describedby"]],
    section: [["data-footnotes"], ["className"]],
  },
  tagNames: [
    ...(defaultSchema.tagNames || []),
    // Markdown basic
    "h1",
    "h2",
    "h3",
    "h4",
    "h5",
    "h6",
    "p",
    "strong",
    "em",
    "code",
    "pre",
    "blockquote",
    "ol",
    "ul",
    "li",
    "table",
    "thead",
    "tbody",
    "tr",
    "td",
    "th",
    "a",
    "span",
    "div",
    "sup",
    "sub",
    "section",
    // KaTeX MathML
    "math",
    "mrow",
    "mi",
    "mo",
    "mn",
    "msup",
    "msub",
    "msubsup",
    "mfrac",
    "msqrt",
    "mstyle",
    "semantics",
    "annotation",
    // KaTeX HTML structure
    "svg",
    "path",
    "g",
    "line",
    "use",
    "style",
  ],
};

export async function renderMarkdown(markdown: string) {
  // 提取 TOC 节点（不会插入 markdown）
  const ast = unified().use(parse).parse(markdown);
  const tocResult = toc(ast, { maxDepth: 3 });
  let tocMarkdown = "";
  if (tocResult.map) {
    const tocAst = { type: "root" as const, children: [tocResult.map] };
    const hast = await unified().use(remarkRehype).run(tocAst);
    tocMarkdown = unified().use(rehypeStringify).stringify(hast);
  }

  const file = await unified()
    .use(parse) // ✅ 解析 Markdown → MDAST
    .use(remarkFrontmatter) // ✅ 支持 YAML Frontmatter
    .use(remarkGfm) // ✅ 支持 GFM（表格、任务列表等）
    .use(remarkMath) // ✅ 支持 $ 和 $$ 数学表达式
    .use(remarkRehype, { allowDangerousHtml: true }) // ✅ 转换为 HAST，可携带 HTML
    .use(rehypekSlug, {
      prefix: "",
    }) // 给标题加 id 配合目录实现锚点功能
    .use(rehypeRaw) // ⚠️ 必须在 sanitize 之前使用，确保 HTML 解析
    .use(rehypeKatex) // ✅ 渲染 math → KaTeX
    .use(rehypeHighlight) // ✅ 渲染代码高亮
    .use(rehypeSanitize, {
      ...katexSchema,
      clobberPrefix: "", // 删除 id 前缀
    }) // 防止因为使用 rehypeRaw 导致的 xxs 注入
    .use(rehypeStringify) // 输出 HTML 字符串
    .process(markdown);

  return {
    contentHTML: file.toString(), // 主体内容 HTML
    tocCatalogHTML: tocMarkdown.toString(), // 目录 HTML
  };
}
